home *** CD-ROM | disk | FTP | other *** search
- {*********************************************************************}
- {* N E T F I L E *}
- {*-------------------------------------------------------------------*}
- {* Task : Implements network supporting file functions. *}
- {*-------------------------------------------------------------------*}
- {* Author : Michael Tischer *}
- {* Developed on : 09/07/91 *}
- {* Last update : 01/29/92 *}
- {*********************************************************************}
-
- unit NetFileP;
-
- interface
-
- uses Crt, Dos, DDPlus; { Add CRT, DOS and DDPlus units }
-
- const {-- Types of file access available -----------------------------}
-
- fm_r = 0; { Read-only }
- fm_w = 1; { Write-only }
- fm_rw = 2; { Read and write in normal Pascal mode }
-
- {-- Types of file protection -----------------------------------}
-
- sm_comp = $00; { Compatibility mode, no file protection }
- sm_rw = $10; { Read and write prohibited by others }
- sm_r = $20; { Read by others permitted, writing prohibited }
- sm_w = $30; { Reading and writing by others permitted }
- sm_no = $40; { All permitted, protected by record lock }
-
- {-- Possible errors during procedure calls ---------------------}
-
- NE_OK = $00; { No error }
- NE_FileNotFound = $02; { Error: File not found }
- NE_PathNotFound = $03; { Error: Path not found }
- NE_TooManyFiles = $04; { Error: Too many open files }
- NE_AccessDenied = $05; { Error: Access to file denied }
- NE_InvalidHandle = $06; { Error: Invalid file handle }
- NE_AccessCode = $07; { Error: Illegal access code }
- NE_Share = $20; { Violation of Share rights }
- NE_Lock = $21; { Error while (un)locking a record }
- NE_ShareBuffer = $24; { Share buffer overflow }
-
- var NetError : integer; { Error number from DOS interrupt }
-
- function ShareInst : boolean; { Share installed? }
-
- function NetErrorMsg( Number : word ) : string; { Error message }
-
- procedure NetReset( FName : string; { Open file }
- AMode : integer;
- RecS : word;
- var DFile );
-
- procedure NetRewrite( FName : string; { Open new file }
- AMode : integer;
- RecS : word;
- var DFile );
-
- procedure NetClose( var DFile ); { Close file }
-
- function NetLock( var DFile; { Lock file range }
- RecNo : longint;
- RngNum : longint ) : boolean;
-
- function NetUnlock( var DFile; { Unlock file range }
- RecNo : longint;
- RngNum : longint ) : boolean;
-
- function Is_NetOpen( var DFile ) : boolean; { Is file open? }
-
- function Is_NetWriteOk( var DFile ) : boolean; { Writing to file O.K. }
-
- function Is_NetReadOk( var DFile ) : boolean; { Reading from file O.K.}
-
- {-- The Read, Write and Seek procedures only work with files set in -}
- {-- input-output mode. The following procedures must be used if -}
- {-- files must be opened in other modes. -}
-
- procedure NetWrite( var DFile; { Write to a file }
- var FData );
-
- procedure NetRead( var DFile; { Read from a file }
- var FData );
-
- procedure NetSeek( var DFile; { Position file pointer }
- RecNo : longint );
-
- implementation
-
- const {-- Function numbers for DOS calls -----------------------------}
-
- FCT_OPEN = $3D; { Function: Open file with handle }
- FCT_CLOSE = $3E; { Function: Close file with handle }
- FCT_CREATE = $3C; { Function: Create file with handle }
- FCT_WRITE = $40; { Function: Write to file }
- FCT_READ = $3F; { Function: Read from file }
- FCT_LSEEK = $42; { Function: Set file pointer }
- FCT_REC_LOCK = $5C; { Function: Record locking }
-
- {-- Function & interrupt numbers for other interrupt calls -----}
-
- MULTIPLEX = $2F; { Multiplex interrupt }
- FCT_SHARE = $1000; { Install text for Share }
-
- {-- Turbo Pascal file identifiers ------------------------------}
-
- fmClosed = $D7B0; { File closed }
- fmInput = $D7B1; { File opened for reading }
- fmOutput = $D7B2; { File opened for writing }
- fmInOut = $D7B3; { File opened for reading and writing }
-
- {*********************************************************************}
- {* ShareInst : Installs test for Share. *}
- {* Input : None *}
- {* Output : TRUE if Share is installed *}
- {* Global var. : NetError/W (error status after call) *}
- {*********************************************************************}
-
- function ShareInst : boolean;
-
- var regs : registers; { Processor registers for interrupt call }
-
- begin
- regs.ax := FCT_SHARE; { Test for installed Share }
- intr( MULTIPLEX, regs ); { Call multiplex interrupt }
- ShareInst := ( regs.al = $FF ); { Return result }
- NetError := NE_OK; { No error }
- end;
-
- {*********************************************************************}
- {* NetErrorMsg : Error message text. *}
- {* Input : Error number *}
- {* Output : Meaning *}
- {*********************************************************************}
-
- function NetErrorMsg( Number : word ) : string;
-
- var Sdummy : string;
-
- begin
- case Number of
- NE_OK : NetErrorMsg := 'No error';
- NE_FileNotFound : NetErrorMsg := 'File not found';
- NE_PathNotFound : NetErrorMsg := 'Path not found';
- NE_TooManyFiles : NetErrorMsg := 'Too many files open';
- NE_AccessDenied : NetErrorMsg := 'File access denied';
- NE_InvalidHandle : NetErrorMsg := 'Invalid file handle';
- NE_AccessCode : NetErrorMsg := 'Illegal access code';
- NE_Share : NetErrorMsg := 'Violation of Share rights';
- NE_Lock : NetErrorMsg := 'Error during record lock';
- NE_ShareBuffer : NetErrorMsg := 'Share buffer overflow';
- else begin
- str( Number, Sdummy );
- NetErrorMsg := 'DOS error: ' + Sdummy;
- end;
- end;
- end;
-
- {*********************************************************************}
- {* NetCreate : Creates a file. *}
- {* Input : Filename, opening mode, record size *}
- {* Output : Opened file *}
- {* Global var. : NetError/W (error status after call) *}
- {*********************************************************************}
-
- procedure NetRewrite( FName : string;
- AMode : integer;
- RecS : word;
- var DFile );
-
- var regs : registers; { Processor registers for interrupt call }
- FName2 : string; { Filename for local access }
-
- begin
- FName2 := FName + #0; { Copy and prepare filename }
- with regs do
- begin
- ds := seg( FName2[ 1 ] ); { Assign filename }
- dx := ofs( FName2[ 1 ] );
- ah := FCT_CREATE; { Function number: Open file }
- cx := 0 ; { File attribute }
- msdos( regs ); { Interrupt call }
- if ( ( flags and fcarry ) = 0 ) then { Open successful? }
- begin
- bx := ax; { Handle in register BX }
- ah := FCT_CLOSE; { Function number: Close file }
- msdos( regs );
- if ( ( flags and fcarry ) = 0 ) then { Close successful? }
- NetReset( FName, AMode, Recs, DFile ) { Open file }
- else
- NetError := ax; { Note error number }
- end
- else
- NetError := ax; { Note error number }
- end;
- end;
-
- {*********************************************************************}
- {* NetReset : Opens a specific file. *}
- {* Input : Filename, open mode, record size *}
- {* Output : Opened file *}
- {* Global var. : NetError/W (error status after call) *}
- {*********************************************************************}
-
- procedure NetReset( FName : string;
- AMode : integer;
- RecS : word;
- var DFile );
-
- var regs : registers; { Processor registers for interrupt call }
-
- begin
- FName := FName + #0; { Filename must end with #0 }
- with regs do
- begin
- ds := seg( FName[ 1 ] ); { Assign filename }
- dx := ofs( FName[ 1 ] );
- ah := FCT_OPEN; { Function number: Open file }
- al := AMode; { Status byte for access mode and locking }
- msdos( regs ); { Interrupt call }
- if ( ( flags and fcarry ) = 0 ) then { Open successful? }
- begin
- NetError := NE_OK; { No error }
- with filerec( DFile ) do
- begin
- move( FName[ 1 ], filerec( DFile ).Name, { Assign }
- length( FName ) ); { filename }
- Handle := ax; { File handle }
- RecSize := RecS; { Specify record size }
- case ( AMode and $0F ) of { Specify Pascal file mode }
- fm_r : Mode := fmInput;
- fm_w : Mode := fmOutput;
- fm_rw : Mode := fmInOut;
- end;
- end;
- end
- else
- begin
- NetError := ax; { Note error number }
- filerec( DFile ).Mode := fmClosed; { File not opened }
- end;
- end;
- end;
-
- {*********************************************************************}
- {* NetClose : Closes a file. *}
- {* Input : File handle *}
- {* Output : None *}
- {*********************************************************************}
-
- procedure NetClose( var DFile );
-
- var regs : registers; { Processor registers for interrupt call }
-
- begin
- if ( Filerec( DFile ).Mode <> fmClosed ) then { File open? }
- begin
- with regs do
- begin
- ah := FCT_CLOSE; { Function number: Close file }
- bx := FileRec( DFile ).Handle; { File handle }
- msdos( regs ); { Interrupt call }
- end;
- FileRec( DFile ).Mode := fmClosed; { Close file }
- NetError := NE_OK; { No error }
- ReleaseTimeSlice; {Added by Bob Dalton - Gives up timeslice}
- end
- else
- NetError := NE_InvalidHandle; { File not open }
- end;
-
- {*********************************************************************}
- {* Locking : Locks or unlocks a file range. *}
- {* Input : File handle, operation, offset for start of file, *}
- {* length of range to be (un)locked *}
- {* Output : TRUE if successful *}
- {* Global var. : NetError/W (error status after call) *}
- {* Info : Call NetLock and NetUnlock for internal access only.*}
- {*********************************************************************}
-
- function Locking( Handle : word;
- Operation : byte;
- Offset : longint;
- WrdLen : longint ) : boolean;
-
- var
- regs : registers; { Processor registers for interrupt call }
- W101 : Word;
- W102 : Word;
- W103 : Boolean;
- begin
- W101:=0;
- W102:=0;
- W103:=False;
-
- {Note: I have added a looping routine to this function which will
- loop until it's successful OR 20,000 times (6-8 seconds) whichever
- comes first. The loop is also designed to give up a time slice
- every 100 iterations of the loop. Bob Dalton}
-
- Repeat
- with regs do
- begin
- ah := FCT_REC_LOCK; { Function number for interrupt call }
- al := Operation; { 0 = Lock, 1 = Unlock }
- bx := Handle; { File handle }
- cx := offset shr 16; { High word offset }
- dx := offset and $FFFF; { Low word offset }
- si := WrdLen shr 16; { High word length }
- di := WrdLen and $FFFF; { Low word length }
- msdos( regs ); { Interrupt call }
- if ( ( flags and fcarry ) = 0 ) then { Locking successful? }
- begin
- Locking := true; { No error }
- W103:=True;
- NetError := NE_OK;
- end
- else
- begin
- Locking := false;
- W103:=False;
- NetError := ax; { Note error number }
- end;
- Inc(W101);
- IF W101=100 then
- Begin
- Inc(W102);
- ReleaseTimeSlice;{Added by Bob Dalton - Gives up timeslice}
- W101:=0;
- End;
- end;
- UNTIL (W103=True) or (W102=200);
- ReleaseTimeSlice; {Added by Bob Dalton - Gives up timeslice}
- end;
-
- {*********************************************************************}
- {* NetLock : Locks records. *}
- {* Input : File, record number, number of records to be locked *}
- {* Output : TRUE if successful *}
- {* Global var. : NetError/W (error status after call) *}
- {*********************************************************************}
-
- function NetLock( var DFile;
- RecNo : longint;
- RngNum : longint ) : boolean;
-
- begin
- NetLock := Locking( filerec( DFile ).Handle, 0,
- filerec( DFile ).Recsize * RecNo,
- filerec( DFile ).Recsize * RngNum );
- end;
-
- {*********************************************************************}
- {* NetUnLock : Unlocks locked records. *}
- {* Input : File, record number, number of records to be locked *}
- {* Output : TRUE if successful *}
- {* Global var. : NetError/W (error status after call) *}
- {*********************************************************************}
-
- function NetUnlock( var DFile;
- RecNo : longint;
- RngNum : longint ) : boolean;
- begin
- NetUnLock := Locking( filerec( DFile).Handle, 1,
- filerec( DFile ).Recsize * RecNo,
- filerec( DFile ).Recsize * RngNum );
- end;
-
- {*********************************************************************}
- {* Is_NetWriteOk : Enables file output. *}
- {* Input : File *}
- {* Output : TRUE if output is enabled *}
- {*********************************************************************}
-
- function Is_NetWriteOk( var DFile ) : boolean;
-
- begin
- with Filerec( DFile ) do
- Is_NetWriteOk := ( Mode = fmOutput ) or ( Mode = fmInOut );
- end;
-
- {*********************************************************************}
- {* Is_NetReadOk : Enables file input. *}
- {* Input : File *}
- {* Output : TRUE if output is enabled *}
- {*********************************************************************}
-
- function Is_NetReadOk( var DFile ) : boolean;
-
- begin
- with Filerec( DFile ) do
- Is_NetReadOk := ( Mode = fmInput ) or ( Mode = fmInOut );
- end;
-
- {*********************************************************************}
- {* Is_NetOpen : Opens file. *}
- {* Input : File *}
- {* Output : TRUE if file is open *}
- {*********************************************************************}
-
- function Is_NetOpen( var DFile ) : boolean;
-
- begin
- with Filerec( DFile ) do
- Is_Netopen := ( Mode = fmInput ) or ( Mode = fmOutput ) or
- ( Mode = fmInOut );
- end;
-
- {*********************************************************************}
- {* NetWrite : Writes to file. *}
- {* Input : File, data *}
- {* Output : None *}
- {* Info : Output is only possible in Pascal procedures when *}
- {* files have been opened in input-output mode. *}
- {* Attention: No type checking performed here. *}
- {*********************************************************************}
-
- procedure NetWrite( var DFile;
- var FData );
-
- var regs : registers; { Processor registers for interrupt call }
-
- begin
- with regs do
- begin
- ds := seg( FData ); { Data address }
- dx := ofs( FData );
- ah := FCT_WRITE; { Function number: Write file }
- bx := filerec( DFile ).Handle; { File handle }
- cx := filerec( DFile ).Recsize; { Number of bytes }
- msdos( regs ); { Interrupt call }
- if ( ( flags and fcarry ) = 0 ) then { Write successful? }
- NetError := NE_OK { No error }
- else
- NetError := ax; { Note error number }
- end;
- end;
-
- {*********************************************************************}
- {* NetRead : Reads from file. *}
- {* Input : File, variable for accessing data *}
- {* Output : Data *}
- {* Info : Output is only possible in Pascal procedures when *}
- {* files have been opened in input-output mode. *}
- {* Attention: No type checking performed here. *}
- {*********************************************************************}
-
- procedure NetRead( var DFile;
- var FData );
-
- var regs : registers; { Processor registers for interrupt call }
-
- begin
- with regs do
- begin
- ds := seg( FData ); { Data address }
- dx := ofs( FData );
- ah := FCT_READ; { Function number: Read file }
- bx := filerec( DFile ).Handle; { File handle }
- cx := filerec( DFile ).Recsize; { Number of bytes }
- msdos( regs ); { Interrupt call }
- if ( ( flags and fcarry ) = 0 ) then { Write successful? }
- NetError := NE_OK { No error }
- else
- NetError := ax; { Note error number }
- end;
- end;
-
- {*********************************************************************}
- {* NetSeek : Sets file pointer. *}
- {* Input : File, record number *}
- {* Output : None *}
- {* Info : Output is only possible in Pascal procedures when *}
- {* files have been opened in input-output mode. *}
- {*********************************************************************}
-
- procedure NetSeek( var DFile;
- RecNo : longint );
-
- var regs : registers; { Processor registers for interrupt call }
-
- begin
- with regs do
- begin
- ah := FCT_LSEEK; { Function number: Set file pointer }
- al := 0; { Absolute position for start of file }
- bx := filerec( DFile ).Handle; { File handle }
- RecNo := RecNo * filerec( DFile ).Recsize; { Offset in bytes }
- cx := RecNo shr 16; { High word offset }
- dx := recNo and $FFFF; { Low word offset }
- msdos( regs ); { Interrupt call }
- if ( ( flags and fcarry ) = 0 ) then { Write successful? }
- NetError := NE_OK { No error }
- else
- NetError := ax; { Note error number }
- end;
- end;
-
- begin
- end.
-